//
//  KCTDialPushVC.swift
//  BLEManagerSwiftDemo
//
//  Created by Qinsz on 2019/5/31.
//  Copyright © 2019年 Qinsz. All rights reserved.
//

import UIKit

class KCTDialPushVC: UIViewController,BLEDialBackgroundPushDelegate,BLENetDialPushDelegate {
    

    private var dialBackgroundTask:KCTBLEDialBackgroundPushTask?
    private var netDialTask:KCTBLENetDialPushTask?
    @IBOutlet weak var outputView: UITextView!
    
    private var bleShell = KCTSingleBLEShell.sharedInstance

    static var StartTimekey = "StartTimekey"
    static var DialIdKey = "DialIdKey"

    override func viewDidLoad() {
        super.viewDidLoad()
         //Do any additional setup after loading the view.
        
    }
    
    @IBAction func clickBack(_ sender: Any) {
        self.navigationController?.popViewController(animated: true)
    }
    
    
    @IBAction func clickCheckDialStatus(_ sender: Any) {
        
        outputView.text = nil
        
        self.showTextInput(title: "查询表盘相关信息", message: "0-表盘状态,1-表盘列表,2-自定义表盘信息,3-背景图信息") {[weak self] (text) in
            if let dataId = Int(text) {
                
                var baseTask:KCTOldBLETaskBase?
                
                switch dataId {
                case 0://
                    let task = KCTOldBLETaskReadDialStatus.init(completion: {[weak self] (tsk, status, error) -> (Void) in
                        self?.outputView.text = ResultContent(title: "表盘状态", error: error, rspDes: "\(status?.yy_modelToJSONObject() ?? "模型转json失败")")
                    })
                    baseTask = task
                    
                case 1:
                    let task = KCTOldBLETaskReadDialListInfo.init(completion: {[weak self] (tsk, listInfo, error) -> (Void) in
                        self?.outputView.text = ResultContent(title: "自定义表盘信息", error: error, rspDes: "\(listInfo?.yy_modelToJSONObject() ?? "模型转json失败")")
                    })
                    baseTask = task
                    
                case 2:
                    let task = KCTOldBLETaskReadDialCustomConfig.init(completion: {[weak self] (tsk, config, error) -> (Void) in
                        self?.outputView.text = ResultContent(title: "自定义背景图信息", error: error, rspDes: "\(config?.yy_modelToJSONObject() ?? "模型转json失败")")
                        
                        if let `config` = config {
                            let f = NSData.init(data: `config`.generateFullFeaturesData())
                            let str = f.base64EncodedString(options: .lineLength64Characters)
                            IPrint("str00=\(str)")
                            
                            IPrint("str01=\(config.generateDeviceFeatureRaw())")
                        }
                    })
                    baseTask = task
                    
                case 3:
                    let task = KCTOldBLETaskReadDialBgConfig.init(completion: {[weak self] (tsk, config, error) -> (Void) in
                        self?.outputView.text = ResultContent(title: "表盘列表", error: error, rspDes: "\(config?.yy_modelToJSONObject() ?? "模型转json失败")")
                    })
                    baseTask = task
                    
                default:
                    SVProgressHUD.showInfo(withStatus: "输入有误")
                }
                if let tsk = baseTask {
                    self?.bleShell.resume(baseTask: tsk)
                }
            }else{
                SVProgressHUD.showInfo(withStatus: "输入有误")
            }
        }
    }

    
    /// 设置当前表盘
    @IBAction func clickUserDial(_ sender: Any) {
        
        self.showTextInput(title: "输入表盘id", message: nil) {[weak self] (text) in
            if let dialId = UInt32(text){
                let task = KCTOldBLETaskSetCurrentDial.init(completion: {[weak self] (tsk,error) -> (Void) in
                    self?.outputView.text = ResultContent(title: "删除表盘", error: error, rspDes: nil)
                })
                task.currentDialId = dialId
                self?.bleShell.resume(baseTask: task)
            }else{
                SVProgressHUD.showInfo(withStatus: "输入有误")
            }
        }
    }
    
    
    /// 删除表盘
    @IBAction func clickDeleteDial(_ sender: Any) {
        
        self.showTextInput(title: "删除表盘", message: "输入表盘id") {[weak self] (text) in
            
            if let dialId = UInt32(text){
                
                let task = KCTOldBLETaskDeleteDial.init(completion: {[weak self] (tsk,error) -> (Void) in
                    self?.outputView.text = ResultContent(title: "删除表盘", error: error, rspDes: nil)
                })
                task.deleteDialId = dialId
                self?.bleShell.resume(baseTask: task)
                
            }else{
                SVProgressHUD.showInfo(withStatus: "输入有误")
            }
        }
    }
    
    /// 删除背景
    @IBAction func clickDeleteDialBG(_ sender: Any) {
        
        let task = KCTOldBLETaskDeleteDialBG.init {[weak self] (tsk,error) -> (Void) in
            self?.outputView.text = ResultContent(title: "删除背景", error: error, rspDes: nil)
        }
        bleShell.resume(baseTask: task)
    }
    
    
    /// 背景推送集成工具
    @IBAction func clickIntegrateDialBgPush(_ sender: Any) {
        
        self.outputView.text = nil
        
        guard let image = UIImage.init(named: "dialBG.jpg") else {
            SVProgressHUD.showError(withStatus: "缺少背景图文件")
            IPrint("背景推送失败:缺少背景图文件")
            self.outputView.text = "背景推送失败:缺少背景图文件"
            return
        }
        
        /// 1、修改MTU可以提高蓝牙写入效率传输速度，但MTU过大可能导致设备端的异常，原则上参考通过指令KCTOldBLETaskReadBasicFirmwareInfos返回的MTU大小；2、提高flash荷载大小，可以减少发送过程中与设备的通信次数，以此提高传输速度，荷载大小视设备而定，但一般都不小于150。
        self.showMultiTextInput(title: "MTU&Flash荷载", message: nil, lines: 2, placeHolders: ["填写MTU","填写Flash最大荷载"], contents: ["20","150"]) {[weak self] (contents) in
            
            guard let mtu = UInt16(contents[0]) else {
                SVProgressHUD.showError(withStatus: "输入有误")
                IPrint("背景推送失败:MTU填写有误")
                self?.outputView.text = "背景推送失败:最大荷载填写有误"
                return
            }
            
            guard let maxPayload = Int(contents[1]) else {
                SVProgressHUD.showError(withStatus: "输入有误")
                IPrint("背景推送失败:最大荷载填写有误")
                self?.outputView.text = "背景推送失败:最大荷载填写有误"
                return
            }
            
            self?.bleShell.MTU = mtu
            // 启动背景推送
            self?.dialBackgroundTask = KCTBLEDialBackgroundPushTask.init(srcImage: image, dialID: 0xffffffff)
            self?.dialBackgroundTask?.maxFlashPayload = maxPayload
            self?.dialBackgroundTask?.delegate = self
            IPrint("ℹ️Flash荷载大小:\(self?.dialBackgroundTask!.maxFlashPayload ?? 0)")
            self?.dialBackgroundTask?.resume()
        }
    }
    
    
    //MARK:-推送背景代理
    func BLEDialBackgroundPushProgress(task: KCTBLEDialBackgroundPushTask, successCount: Int, totalCount: Int) {
        
        if successCount == 0{
            // 开始
            self.setStartTime(startTime: Date.init().timeIntervalSince1970, task: task)
        }
        
        let progress = Float(successCount)/Float(totalCount)
        SVProgressHUD.showProgress(progress, status: "正在推送背景\n\(successCount)/\(totalCount)")
    }
    func BLEDialBackgroundPushCompletion(task: KCTBLEDialBackgroundPushTask, success: Bool, failureType: DialBGFailureType, failureDes: String?) {
        if success == true {
            SVProgressHUD.showSuccess(withStatus: "背景推送成功")
            let endTime = Date.init().timeIntervalSince1970
            let content = String.init(format: "背景推送成功,用时'%.3f'秒", endTime - self.getStartTime(task: task))
            self.outputView.text = content
            IPrint("✅\(content)")
        }else{
            SVProgressHUD.showError(withStatus: "背景推送失败")
            IPrint("背景推送失败,type=\(failureType.rawValue),reason='\(failureDes ?? "")'")
            outputView.text = "背景推送失败,type=\(failureType.rawValue),reason='\(failureDes ?? "")'"
        }
        self.bleShell.MTU = 20
    }
    
    @IBAction func clickReqDialList(_ sender: Any) {
        self.outputView.text = nil
        SVProgressHUD.show()
        
        let firmwareTask = KCTOldBLETaskReadFirmwareInfos.init { (firmwareTsk, firmwareErr, infos) in
            guard let `infos` = infos else{
                SVProgressHUD.dismiss()
                self.outputView.text = "获取表盘列表失败,获取固件信息失败"
                return
            }
            
            let configTask = KCTOldBLETaskReadDialCustomConfig.init { (configTsk, config, configErr) -> (Void) in
                
                guard let config = config else{
                    SVProgressHUD.dismiss()
                    self.outputView.text = "获取表盘列表失败,获取表盘特征失败"
                    return
                }
                
                self.reqDialList(serialsNum: infos.serialNumber, featureRaw: config.generateDeviceFeatureRaw())
            }
            configTask.resume()
        }
        firmwareTask.resume()
    }
    
    private func reqDialList(serialsNum:Int,featureRaw:String){
        let task = KCTHTTPSession.share.optionalDialListTask(fromProduct: false, appKey: TestAPPKey, secretKey: TestSecretKey, deviceFeatureRaw: featureRaw, adaptiveNumber: serialsNum, option: 0x0B) { (rsp, error) -> (Void) in
            DispatchQueue.main.async {
                
                SVProgressHUD.dismiss()
                guard let `rsp` = rsp else {
                    self.outputView.text = "获取表盘列表失败,网络请求失败"
                    return
                }
                
                let array = NSMutableArray.init()
                for unit in rsp.dialList {
                    array.add(unit)
                }
                self.outputView.text = "\(array.yy_modelToJSONObject() ?? "")"
                
            }
        }
        task?.resume()
    }
    
    @IBAction func clickNewDialPush(_ sender: Any) {
        
        self.outputView.text = nil
        let placeHolders = ["表盘id","表盘位"]
        let contents = ["","0"]
        
        self.showMultiTextInput(title: "表盘推送", message: nil, lines: 2, placeHolders: placeHolders, contents: contents) { (inputs) in
            
            guard let dialId = UInt32(inputs[0]),let index = UInt8(inputs[1]) else {
                self.outputView.text = "输入有误"
                return
            }
            
            // 修改MTU
            let basicTask = KCTOldBLETaskReadBasicFirmwareInfos.init { (tsk, infos, error) in
                if let `infos` = infos {
                    self.bleShell.MTU = infos.MTU-3 > 20 ? UInt16(infos.MTU-3):20
                }
            }
            basicTask.resume()
            
            SVProgressHUD.show()
            let netDialTask = KCTBLENetDialPushTask.init()
            netDialTask.dialPanelId = dialId
            netDialTask.appKey = TestAPPKey
            netDialTask.secretKey = TestSecretKey
            netDialTask.fromProduct = false
            netDialTask.downloadTimeout = 15
            netDialTask.dialIndex = index
            netDialTask.maxFlashPayload = 155
            netDialTask.delegate = self
            
            self.netDialTask = netDialTask
            
            self.netDialTask?.resume()
        }
    }
    
    func BLENetDialPushProgress(task: KCTBLENetDialPushTask, successCount: Int, totalCount: Int) {
        if successCount == 0{
            // 开始
            self.setStartTime(startTime: Date.init().timeIntervalSince1970, task: task)
        }
        let progress = Float(successCount)/Float(totalCount)
        SVProgressHUD.showProgress(progress, status: "正在推送表盘\n\(successCount)/\(totalCount)")
    }
    
    func BLENetDialPushCompletion(task: KCTBLENetDialPushTask, success: Bool, failureType: DialFailureType, failureDes: String?) {
        
        if success == true {
            SVProgressHUD.showSuccess(withStatus: "表盘推送成功")
            let dialId = self.getDialId(task: task)
            let endTime = Date.init().timeIntervalSince1970
            let content = String.init(format: "表盘推送成功(dialId='\(dialId)'),用时'%.3f'秒", endTime - self.getStartTime(task: task))
            self.outputView.text = content
            IPrint("✅\(content)")
            
            if dialId != 0 {
                // 将新推送的表盘设置为当前表盘
                let setCurrentTask = KCTOldBLETaskSetCurrentDial.init(completion: {(tsk,error) -> (Void) in
                    if let err = error {
                        IPrint("⚠️推送表盘成功后设定为当前表盘失败:\(err)")
                        return
                    }
                    IPrint("✅推送表盘后设定为当前表盘成功(dialId = \(dialId))")
                })
                setCurrentTask.currentDialId = dialId
                setCurrentTask.resume()
            }
            
        }else{
            
            // 与传入参数有关的错误。
            switch failureType {
            case .DialIndexOccupied:
                IPrint("❌表盘位被占用，需要删除被占用的表盘位，或者重新指定表盘位")
            case .DialInexOverBound:
                IPrint("❌表盘位越界，需要重新指定表盘位")
            case .InvalidDialRawFeature:
                IPrint("❌表盘特征参数错误")
            default:
                IPrint("❌其它错误")
            }
            SVProgressHUD.showError(withStatus: "表盘推送失败")
            IPrint("表盘推送失败,type=\(failureType.rawValue),reason='\(failureDes ?? "")'")
            outputView.text = "表盘推送失败,type=\(failureType.rawValue),reason='\(failureDes ?? "")'"
        }
        self.bleShell.MTU = 20
        
    }
    
    private func setStartTime(startTime:TimeInterval,task:NSObject){
        objc_setAssociatedObject(task, &KCTDialPushVC.StartTimekey, startTime, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }
    private func getStartTime(task:NSObject)->TimeInterval{
        let time = objc_getAssociatedObject(task, &KCTDialPushVC.StartTimekey) as? TimeInterval ?? 0
        return time
    }
    
    private func setDialId(dialId:UInt32,task:NSObject) {
        objc_setAssociatedObject(task, &KCTDialPushVC.DialIdKey, dialId, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    }
    private func getDialId(task:NSObject) -> UInt32 {
        let dialId = objc_getAssociatedObject(task, &KCTDialPushVC.DialIdKey) as? UInt32 ?? 0
        return dialId
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }
}




